/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-04-15 18:23
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第六章 函数
 *       6.1 函数基础
 * 
 ********************************************************************************************************************************/


#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <stdexcept>    //标准库异常类型


using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::vector;
using std::runtime_error;

int fact(void){
    int ret = 1;
    int c;

    cout << "Please enter a number, it will print the 3! of this number" << endl;
    cin >> c;

    try {
        if(c < 0)
            throw runtime_error("value is negative");

        while(c > 0){
            ret *= c;
            --c;
        }
    } catch (runtime_error err) {
        cout << "Exception" << err.what() << endl;
    }
    
    return ret;
}

size_t count_calls()
{
    static size_t ctr = 0;


    return ctr++;
}

int main(int argc, char *argv[])
{
    //
    // 6.1 节练习
    // 练习6.1: 实参和形参的区别是什么？
    //

    //在函数调用时，通过调用符(calling operator)，隐式的声明并定义形参，并初始化形参，形参的初始值为实参
    //实参和形参的数量和类型必须一一对应，第一个实参用来初始化第一个形参，第二个实参用来初始化


    //
    // 6.1 节练习
    // 练习6.2: 请指出下列哪个函数有错误？为什么，应该如何修改
    //


    //
    // 6.1 节练习
    // 练习6.3: 编写你自己的fact函数，上机检查是否正确
    //


    //
    // 6.1 节练习
    // 练习6.4: 编写一个与用户交互的函数，要求用户输入一个数字，计算该数字的阶乘
    //
    int ret = fact();
    cout << "ret of call function is " << ret << endl;



    //=========================================================================
    //=========================================================================
    //=========================================================================
    //=========================================================================
    //=========================================================================
    //=========================================================================

    //
    // 6.1.1 节练习
    // 练习6.6: 说明形参，局部变量，以及静态局部变量的区别。编写一个函数，同时用到这三种形式
    //
    //1. 作用域相同，作用域都是在函数体代码块内
    //2. 生命周期不同
    //   形参和局部变量都是自动对象，在函数调用的时候用实参来初始化形参，在函数语句块结束的地方
    //   释放形参对象。
    //   局部变量在函数体执行到变量定义所在的语句时，初始化局部变量，在函数语句块结束的地方
    //   释放局部变量对象
    //   如果局部变量在定义时有初始值，则用初始值来初始化该自动对象，如果局部变量在定义时没有初始值则
    //   执行默认初始化，内置数据类型的默认初始化为未定义的值。
    //   静态局部变量具有全局生命周期，只带第一次执行到静态局部变量定义的时候执行变量对象初始化，
    //   如果没有提供初始值，将执行值初始化，C++内置数据类型的初始值为0.



    //
    // 6.1.1 节练习
    // 练习6.7: 编写一个函数到第一次调用的时候返回0，以后每次调用返回值加1
    //

    for(size_t i = 0; i != 10; i++)
        cout << "call times " << count_calls() << endl;


    return 0;
}

//错误：函数返回类型与return语句的返回对象类型不匹配
string f()
{
    string s;

    //...
    return s;
}

//错误：没有返回类型
int fw(int i ){}

//错误：形参的中有相同的参数名
int calc(int v1, int v2){}



